import { HarmonyPilotCommentCollection } from "../../../core/comments/HarmonyPilotCommentCollection";
import * as vscode from "vscode";
import { ChatMessage } from '../../../core';
import { BaseLLM } from "../../../core/llm/baseLLM";
import { LLMFactory } from '../../../core/llm/llmFactory';
import { generalCodeReviewPrompt } from "./aiReviewPrompts";
import { ProxyService } from "../../../src/services/proxyService";
import { checkLoginStatus } from "../../utils/authGuard";
import { AnalyticsService } from "../../../src/services/analyticsService";
import { Logger } from "../../../src/logger/Logger";

// 定义错误消息常量
const ERROR_MESSAGES = {
    LLM_NOT_FOUND: "LLM not found",
    NO_ACTIVE_EDITOR: "No active editor found",
    NO_FILE_OPEN: "No file is open",
    NO_DOCUMENT: "No document found",
    LINE_NUMBER_FORMAT_ERROR: "Line number format error",
    LINE_NUMBER_OUT_OF_RANGE: "Line number out of range",
    PARSE_JSON_ERROR: "Parse JSON error",
    LLM_STREAM_CHAT_ERROR: "LLM stream chat error",
};

// 日志记录函数
function logError(message: string, details?: any) {
    console.error(message, details);
    vscode.window.showErrorMessage(message);
}


// 定义提取LLM返回结果中的 JSON 的函数
function extractJsonFromString(str: string): { parsedJson: any | null; remainingStr: string } {
    // 首先尝试使用代码块格式提取
    const codeBlockRegex = /```json\s*([\s\S]*?)\s*```/;
    const codeBlockMatch = str.match(codeBlockRegex);
    
    if (codeBlockMatch && codeBlockMatch[1]) {
        try {
            const parsedJson = JSON.parse(codeBlockMatch[1]);
            const remainingStr = str.slice(codeBlockMatch.index ? codeBlockMatch.index + codeBlockMatch[0].length : 0);
            return { parsedJson, remainingStr };
        } catch (error) {
            logError(ERROR_MESSAGES.PARSE_JSON_ERROR, error);
        }
    }
    
    // 如果代码块格式提取失败，尝试直接解析整个字符串
    try {
        const parsedJson = JSON.parse(str);
        return { parsedJson, remainingStr: "" };
    } catch (error) {
        // 尝试查找可能的JSON对象
        const jsonObjectRegex = /(\{[\s\S]*\})/;
        const jsonMatch = str.match(jsonObjectRegex);
        
        if (jsonMatch && jsonMatch[1]) {
            try {
                const parsedJson = JSON.parse(jsonMatch[1]);
                const remainingStr = str.slice(jsonMatch.index ? jsonMatch.index + jsonMatch[0].length : 0);
                return { parsedJson, remainingStr };
            } catch (jsonError) {
                // 如果仍然解析失败，记录错误
                logError(ERROR_MESSAGES.PARSE_JSON_ERROR, jsonError);
            }
        }
    }

    Logger.error(`解析JSON失败: ${str}`);
    return { parsedJson: null, remainingStr: str };
}

// 获取带行号的完整代码
function getFullLinesCode(document: vscode.TextDocument): string {
    return Array.from({ length: document.lineCount }, (_, i) => {
        const line = document.lineAt(i);
        return `line ${i + 1}: ${line.text}`;
    }).join('\n'); // 将数组转换为字符串
}
// 动态生成提示词
function generatePromptContent(
    generalCodeReviewPrompt: { content: string },
    fullLinesCode: string,
    languageId: string,
    fileName: string,
    startLine: number,
    endLine: number
): string {
    return generalCodeReviewPrompt.content
        .replace("{review_full_code}", fullLinesCode || "")
        .replace("{review_file_type}", languageId || "unknown")
        .replace("{review_file_name}", fileName || "unknown")
        .replace("{review_start_line}", String(startLine + 1))
        .replace("{review_end_line}", String(endLine + 1));
}

// 解析行号，当前强制要求生成单行信息，后续可考虑生成区间信息
function parseLineNumbers(line: string, document: vscode.TextDocument): [number, number] | null {
    const lineNumbers = line.split('-').map(Number).filter(num => !isNaN(num));
    if (lineNumbers.length === 0 || lineNumbers.some(num => num < 1)) {
        logError(ERROR_MESSAGES.LINE_NUMBER_FORMAT_ERROR);
        return null;
    }

    const reviewStartLine = lineNumbers[0];
    const reviewEndLine = lineNumbers.length === 2 ? lineNumbers[1] : reviewStartLine;

    if (reviewStartLine > document.lineCount || reviewEndLine > document.lineCount || reviewEndLine < reviewStartLine) {
        logError(ERROR_MESSAGES.LINE_NUMBER_OUT_OF_RANGE);
        return null;
    }

    return [reviewStartLine - 1, reviewEndLine - 1];
}


// 获取代码片段的位置
function getPosition(document: vscode.TextDocument, startLine: number, endLine: number) {
    const startPosition = new vscode.Position(startLine, 0);
    const endPosition = new vscode.Position(endLine, document.lineAt(endLine).text.length);
    return { startPosition, endPosition };
}

// 异步执行 LLM 代码审查
async function executeLLMReview(
    llm: BaseLLM,
    promptContent: string,
    abortSignal: AbortSignal,
    context: vscode.ExtensionContext
): Promise<string> {
    let buffer = "";
    try {
        for await (const message of ProxyService.getInstance(context)._streamChat([{ role: "user", content: promptContent }], abortSignal)) {
            buffer += message.content;
        }
    } catch (error) {
        logError(ERROR_MESSAGES.LLM_STREAM_CHAT_ERROR, error);
    }
    return buffer;
}

export async function aiReview(commentCollection: HarmonyPilotCommentCollection, llmFactory: LLMFactory, context: vscode.ExtensionContext   ) {
    // 检查登录状态
    const isLoggedIn = await checkLoginStatus(context);
    if (!isLoggedIn) {
        return;
    }

    AnalyticsService.getInstance(context).trackEvent('aiReview');

    const cancellationTokenSource = new vscode.CancellationTokenSource();

    const progressOptions = {
        location: vscode.ProgressLocation.Notification,
        title: "AI Reviewing...",
        cancellable: true
    };

    try {
        await vscode.window.withProgress(progressOptions, async (_, token) => {
            const abortController = new AbortController();

            token.onCancellationRequested(() => {
                vscode.window.showInformationMessage("AI Review cancelled");
                cancellationTokenSource.cancel();
                abortController.abort();
            });

            const llm = llmFactory.getLLM("deepseek-chat");
            if (!llm) {
                logError(ERROR_MESSAGES.LLM_NOT_FOUND);
                return;
            }

            const editor = vscode.window.activeTextEditor;
            if (!editor) {
                logError(ERROR_MESSAGES.NO_ACTIVE_EDITOR);
                return;
            }

            const document = editor.document;
            const currentFile = document.uri.fsPath;
            if (!currentFile) {
                logError(ERROR_MESSAGES.NO_FILE_OPEN);
                return;
            }

            const languageId = document.languageId;
            const fileName = document.fileName;

            const selection = editor.selection;
            const [startLine, endLine] = selection.isEmpty 
                ? [0, document.lineCount - 1] 
                : [selection.start.line, selection.end.line];

            const fullLinesCode = getFullLinesCode(document);
            const promptContent = generatePromptContent(
                generalCodeReviewPrompt,
                fullLinesCode,
                languageId,
                fileName,
                startLine,
                endLine
            );

            const buffer = await executeLLMReview(llm, promptContent, abortController.signal, context);

            const { parsedJson } = extractJsonFromString(buffer);
            if (parsedJson) {
                const reviewComments = parsedJson.review_comments || [];
                
                // 如果没有发现缺陷，显示提示信息
                if (reviewComments.length === 0) {
                    vscode.window.showInformationMessage("AI Review 完成：未发现代码缺陷");
                    return;
                }
                
                for (const commentItem of reviewComments) {
                    const lineNumbers = parseLineNumbers(commentItem.line, document);
                    if (!lineNumbers) { continue; }

                    const [reviewStartLine, reviewEndLine] = lineNumbers;
                    const { startPosition, endPosition } = getPosition(document, reviewStartLine, reviewEndLine);

                    const comment = `检视意见：${commentItem.review_comment} <br>问题类别：${commentItem.categories} <br>严重程度：${commentItem.severity}`;
                    commentCollection.addComment(comment, currentFile, startPosition, endPosition, "");
                }
                
                // 确保评论面板显示并聚焦到第一个评论
                if (reviewComments.length > 0) {
                    vscode.commands.executeCommand('workbench.action.focusCommentsPanel');
                }
            }
        });
    } finally {
        cancellationTokenSource.dispose(); // 确保资源释放
    }
}